#include "nvsram.h"

#define NVSRAM_SIZE		(1*K)


/*		
	nvsram aera:  magic , des, 3des ...
	
	nvsram data struct :
  		chksum[4byte] + data[...]
*/

static NVS_PARA nvs_map[]={
	{NVS_ID_MAGIC, 	0x04, 	0x00},		// valid data: 0xe2c3f3ab
	{NVS_ID_DES, 	0x10, 	0x00+0x04},
	
	{NVS_ID_ERR, 	0x00, 	0x00},
};

static NVS_PARA nvs_get_para_by_id(NVS_ID id)
{
	if(id >= ARRAY_SIZE(nvs_map)){
		return nvs_map[NVS_ID_ERR];
	}

	if(nvs_map[id].oftAddr >= NVSRAM_SIZE){
		return nvs_map[NVS_ID_ERR];
	}

	return nvs_map[id];
}

u8 nvs_write(NVS_ID id, u32 *data, u16 nums)
{
	NVS_PARA para;
	vu32   *pIntAddr = (vu32 *)MML_MEM_SNVSRAM_BASE;
	u32 tbuf[512];
	SYSP_ST *sysp;	
	
	para = nvs_get_para_by_id(id);
	if(para.id == NVS_ID_ERR){
		nvs_debug("[NVS] input id error\n");
		return 1;
	}

	if((nums > para.maxSize)||(!data)){
		nvs_debug("[NVS] input nums error\n");
		return 2;
	}
	
	//nvs_debug("\n[NVS] wr id = %x\n", para.id);

	sysp = sys_para_get();
	if(sysp->sysrunmode == SYS_ERR_AES){
		trng_aes_keygen();
		sysp->sysrunmode = SYS_ERR_KEY;
	}

	if(sysp->sysrunmode == SYS_ERR_KEY){
		*pIntAddr = SYS_AES_MAGIC;
		sysp->sysrunmode = SYS_USER;
	}

	memset(tbuf, 0, sizeof(tbuf));
	tbuf[0] = chksum_add32((u8 *)data, nums*4);
	//nvs_debug("\n[NVS] wr tbuf[0] = %x\n", tbuf[0]);

	memcpy(&tbuf[1], data, nums*4);

	pIntAddr += para.oftAddr;
	for(int nr=0; nr<(nums+1); nr++){
		*pIntAddr = tbuf[nr];
		nvs_debug("[NVS] wr addr=%x, val=%x\n", pIntAddr, tbuf[nr]);
		pIntAddr++;
	}

	return 0;
}

u8 nvs_read(NVS_ID id, u32 *data, u16 nums)
{
	NVS_PARA para;
	vu32   *pIntAddr = (vu32 *)MML_MEM_SNVSRAM_BASE;
	u32 tbuf[512];
	SYSP_ST *sysp;	

	para = nvs_get_para_by_id(id);
	if(para.id == NVS_ID_ERR){
		nvs_debug("[NVS] input id error\n");
		return 1;
	}

	if((nums > para.maxSize)||(!data)){
		nvs_debug("[NVS] input nums error\n");
		return 2;
	}

	sysp = sys_para_get();
	if(sysp->sysrunmode < SYS_USER){
		nvs_debug("[NVS] AES key novalid ...\n");
		//return 3;
	}
	
	//nvs_debug("\n[NVS] rd id = %x\n", para.id);

	pIntAddr += para.oftAddr;
	for(int nr=0; nr<(nums+1); nr++){
		tbuf[nr] = *pIntAddr;
		//nvs_debug("[NVS] rd addr=%x, val=%x\n", pIntAddr, tbuf[nr]);
		pIntAddr++;
	}
	
	if(tbuf[0] != chksum_add32((u8 *)&tbuf[1], nums*4)){
		//nvs_debug("[NVS] rd  chksum err: org = %x, calc = %x\n", tbuf[0], chksum_add32((u8 *)&tbuf[1], nums*4));
		return 3;
	}

	memcpy(data, &tbuf[1], nums*4);

	return 0;
}

u8 nvsram_check(void)
{
	u32  magic;
	SYSP_ST *sysp;	

	sysp = sys_para_get();
	
	nvs_debug("[NV] nvSram check...!!!\n");

	if(trng_check_aes_valid()){
		nvs_debug("[NV] nvSram check error: aes aera not init...!!!\n");
		sysp->sysrunmode = SYS_ERR_AES;
		//return 1;
	}
	
	nvs_read(NVS_ID_MAGIC, &magic, 1);
	if(SYS_AES_MAGIC != magic){
		sysp->sysrunmode = SYS_ERR_KEY;
		nvs_debug("[NV] nvSram check error, magic=%x!!!\n", magic);
		//return 2;
	}
	
	return 0;	
}


